PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | \
PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)
u16 val;
- unsigned int nbars = 0, rom_pos = 0, i;
- static const char warn[] = XENLOG_WARNING
- "%pp disabled: %sBAR [%#lx, %#lx] overlaps with memory map\n";
if ( command_mask )
{
switch ( pci_conf_read8(pdev->sbdf, PCI_HEADER_TYPE) & 0x7f )
{
case PCI_HEADER_TYPE_BRIDGE:
- nbars = PCI_HEADER_BRIDGE_NR_BARS;
- rom_pos = PCI_ROM_ADDRESS1;
if ( !bridge_ctl_mask )
break;
val = pci_conf_read16(pdev->sbdf, PCI_BRIDGE_CONTROL);
}
break;
- case PCI_HEADER_TYPE_NORMAL:
- nbars = PCI_HEADER_NORMAL_NR_BARS;
- rom_pos = PCI_ROM_ADDRESS;
- break;
-
case PCI_HEADER_TYPE_CARDBUS:
/* TODO */
break;
}
#undef PCI_STATUS_CHECK
-
- /* Check if BARs overlap with other memory regions. */
- val = pci_conf_read16(pdev->sbdf, PCI_COMMAND);
- if ( !(val & PCI_COMMAND_MEMORY) || pdev->ignore_bars )
- return;
-
- pci_conf_write16(pdev->sbdf, PCI_COMMAND, val & ~PCI_COMMAND_MEMORY);
- for ( i = 0; i < nbars; )
- {
- uint64_t addr, size;
- unsigned int reg = PCI_BASE_ADDRESS_0 + i * 4;
- int rc = 1;
-
- if ( (pci_conf_read32(pdev->sbdf, reg) & PCI_BASE_ADDRESS_SPACE) !=
- PCI_BASE_ADDRESS_SPACE_MEMORY )
- goto next;
-
- rc = pci_size_mem_bar(pdev->sbdf, reg, &addr, &size,
- (i == nbars - 1) ? PCI_BAR_LAST : 0);
- if ( rc < 0 )
- /* Unable to size, better leave memory decoding disabled. */
- return;
- if ( size && !pci_check_bar(pdev, maddr_to_mfn(addr),
- maddr_to_mfn(addr + size - 1)) )
- {
- /*
- * Return without enabling memory decoding if BAR position is not
- * in IO suitable memory. Let the hardware domain re-position the
- * BAR.
- */
- printk(warn,
- &pdev->sbdf, "", PFN_DOWN(addr), PFN_DOWN(addr + size - 1));
- return;
- }
-
- next:
- ASSERT(rc > 0);
- i += rc;
- }
-
- if ( rom_pos &&
- (pci_conf_read32(pdev->sbdf, rom_pos) & PCI_ROM_ADDRESS_ENABLE) )
- {
- uint64_t addr, size;
- int rc = pci_size_mem_bar(pdev->sbdf, rom_pos, &addr, &size,
- PCI_BAR_ROM);
-
- if ( rc < 0 )
- return;
- if ( size && !pci_check_bar(pdev, maddr_to_mfn(addr),
- maddr_to_mfn(addr + size - 1)) )
- {
- printk(warn, &pdev->sbdf, "ROM ", PFN_DOWN(addr),
- PFN_DOWN(addr + size - 1));
- return;
- }
- }
-
- pci_conf_write16(pdev->sbdf, PCI_COMMAND, val);
}
static void apply_quirks(struct pci_dev *pdev)
uint32_t val = bar->addr |
(map ? PCI_ROM_ADDRESS_ENABLE : 0);
- bar->enabled = header->rom_enabled = map;
+ if ( pci_check_bar(pdev, _mfn(PFN_DOWN(bar->addr)),
+ _mfn(PFN_DOWN(bar->addr + bar->size - 1))) )
+ bar->enabled = map;
+ header->rom_enabled = map;
pci_conf_write32(pdev->sbdf, rom_pos, val);
return;
}
if ( !rom_only &&
- (bar->type != VPCI_BAR_ROM || header->rom_enabled) )
+ (bar->type != VPCI_BAR_ROM || header->rom_enabled) &&
+ pci_check_bar(pdev, _mfn(PFN_DOWN(bar->addr)),
+ _mfn(PFN_DOWN(bar->addr + bar->size - 1))) )
bar->enabled = map;
}
if ( !MAPPABLE_BAR(bar) ||
(rom_only ? bar->type != VPCI_BAR_ROM
- : (bar->type == VPCI_BAR_ROM && !header->rom_enabled)) )
+ : (bar->type == VPCI_BAR_ROM && !header->rom_enabled)) ||
+ /* Skip BARs already in the requested state. */
+ bar->enabled == !!(cmd & PCI_COMMAND_MEMORY) )
continue;
+ if ( !pci_check_bar(pdev, _mfn(start), _mfn(end)) )
+ {
+ printk(XENLOG_G_WARNING
+ "%pp: not mapping BAR [%lx, %lx] invalid position\n",
+ &pdev->sbdf, start, end);
+ continue;
+ }
+
rc = rangeset_add_range(mem, start, end);
if ( rc )
{